#include "watchpoint.h"
#include "expr.h"



#define NR_WP 32

static WP wp_pool[NR_WP];
static WP *head, *free_;

void init_wp_pool() {
	int i;
	for(i = 0; i < NR_WP; i ++) {
		wp_pool[i].NO = i;
		wp_pool[i].next = &wp_pool[i + 1];
	}
	wp_pool[NR_WP - 1].next = NULL;

	head = NULL;
	free_ = wp_pool;
}

/* TODO: Implement the functionality of watchpoint */

WP* new_wp(){
	assert(free_ != NULL);
	//从空闲链表的表头取一个
	WP *temp = free_;
	free_ = free_->next;
	temp->next = NULL;
	temp->flag = true;

	//放入使用中的链表
	if(head==NULL)
		head = temp;
	else{
		WP *p = head;
		while(p->next)
        {
            p = p->next;
        }
		p->next = temp;
	}
	return temp;
}


void free_wp(WP *wp){
	if(wp == NULL)
	    printf("Input something!\n");
	if(wp == head)
	    head = head -> next;
	else{
	   	WP *p = head;
	   	while(p->next!=wp){
            p = p->next;
        }
	   	if(p == NULL)
	   	    return ;
	   	p -> next = wp -> next;
	}
	//将wp插回free表头
	wp -> flag = false;
	wp -> next = free_;
	free_ = wp;
}
void sdb_watchpoint_display(){
    bool flag = true;
	int i;
    for(i = 0 ; i < NR_WP ; i ++){
        if(wp_pool[i].flag){
            printf("Watchpoint.No: %d, expr = \"%s\", old_value = %d, new_value = %d\n",
                    wp_pool[i].NO, wp_pool[i].expr,wp_pool[i].old_value, wp_pool[i].new_value);
                flag = false;
        }
    }
    if(flag) printf("No watchpoint now.\n");
}

void delete_watchpoint(int no){
	int i;
    for(i = 0 ; i < NR_WP ; i ++)
        if(wp_pool[i].NO == no){
            free_wp(&wp_pool[i]);
            return ;
        }
}

bool check_watchpoints()
{
	int i;
	for(i = 0 ; i < NR_WP; i ++){
        if(wp_pool[i].flag)
        {
            bool success = false;
            int tmp = expr(wp_pool[i].expr,&success);
            if(success){
                if(tmp != wp_pool[i].old_value)
                {
					wp_pool[i].new_value = tmp;
                    printf("Triggered surveillance points!watch_point:%d,old_value:%d,new_value:%d\n",
					wp_pool[i].NO,wp_pool[i].old_value,wp_pool[i].new_value);
                    return true;
                }
            }
            else{
                printf("expr error.\n");
                assert(0);
            }
        }
	}
	return false;
}

void create_watchpoint(char* args){
    WP* p =  new_wp();
    strcpy(p -> expr, args);
    bool success = false;
    int tmp = expr(p -> expr,&success);
    if(success) p -> old_value = tmp;
    else printf("创建watchpoint的时候expr求值出现问题\n");
    printf("Create watchpoint No.%d success.\n", p -> NO);
}


